home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / extensions / samples / videotogfx.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  14KB  |  468 lines

  1. /*
  2.  * Copyright (c) 1994 Silicon Graphics, Inc.
  3.  * 
  4.  * Permission to use, copy, modify, distribute, and sell this software and
  5.  * its documentation for any purpose is hereby granted without fee,
  6.  * provided that (i) the above copyright notices and this permission
  7.  * notice appear in all copies of the software and related documentation,
  8.  * and (ii) the name of Silicon Graphics may not be used in any
  9.  * advertising or publicity relating to the software without the specific,
  10.  * prior written permission of Silicon Graphics.
  11.  * 
  12.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  13.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  14.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  15.  * 
  16.  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL,
  17.  * INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY
  18.  * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  19.  * OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
  20.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  21.  * OF THIS SOFTWARE.
  22.  */
  23. /*
  24.  * vidtogfx.c
  25.  *  This VL program demonstrates the Sirius Video board video->graphics ability
  26.  *  using OpenGL.
  27.  *
  28.  * See the usage() function for the command line options (or run with -h).
  29.  * 
  30.  * $Revision: 1.1 $
  31.  */
  32.  
  33. #include <stdlib.h>
  34. #include <stdio.h>
  35. #include <string.h>
  36. #include <getopt.h>
  37. #include <device.h>
  38. #include <vl/vl.h>
  39. #include <vl/dev_sirius.h>
  40. #include <GL/glx.h>
  41. #include "xwindow.h"
  42. #include <X11/keysym.h>
  43.  
  44. /* VL variable */
  45. VLControlValue size, timing, dominance;
  46. VLControlValue   format;
  47. VLServer    svr;
  48. VLPath    path;
  49. VLNode    src;
  50. VLNode    drn;
  51.  
  52. int F1_is_first;                /* Which field is first */
  53.  
  54. /* OpenGL/X variables */
  55. Display *dpy;
  56. Window window;
  57. #ifdef GLX_SGIX_video_source
  58. GLXVideoSourceSGIX glxVideoSource;
  59. #else  /* Make the compiler barf */
  60. GLX_SGIX_video_source is not defined in this version of the library
  61. #endif
  62. GLXContext ctx;
  63. GLfloat zoom = 1;
  64. GLboolean interlace = GL_FALSE;
  65. /* Interlace extension is (partially or fully) implemented */
  66. GLboolean hasInterlace;
  67.  
  68. /*
  69.  * function prototypes
  70.  */
  71. void usage(char *, int);
  72. void InitGfx(int, char **);
  73. void GrabField(int);
  74. void UpdateTiming(void);
  75. void cleanup(void);
  76. void ProcessEvents(void);
  77. static void loop(void);
  78.  
  79. int
  80. main(int argc, char **argv)
  81. {
  82.     int        c, insrc = VL_ANY;
  83.     int        device = VL_ANY;
  84.     short    dev, val;
  85.  
  86.     /* Parse the input string */
  87.     while ((c = getopt(argc, argv, "n:v:h")) != EOF ) {
  88.         switch (c) {
  89.           case 'n':
  90.             device = atoi(optarg);    /* user can override default device */
  91.             break;
  92.           case 'v':
  93.             insrc = atoi(optarg);    /* Check to see input node */
  94.             break;
  95.           case 'h':
  96.             usage(argv[0], EXIT_SUCCESS);
  97.           default:
  98.             usage(argv[0], EXIT_FAILURE);
  99.         }
  100.     }
  101.  
  102.     /* open connection to VL server */
  103.  
  104.     if (!(svr = vlOpenVideo(""))) {
  105.     printf("couldn't open connection to VL server\n");
  106.     exit(EXIT_FAILURE);
  107.     }
  108.  
  109.     /* Get the Video input */
  110.     src = vlGetNode(svr, VL_SRC, VL_VIDEO, insrc);
  111.     /* Get the first Graphics output */
  112.     drn = vlGetNode(svr, VL_DRN, VL_GFX, 0);
  113.  
  114.     /* Create path   */
  115.     path = vlCreatePath(svr, device, src, drn);
  116.     if (path < 0) {
  117.     vlPerror("vlCreatePath");
  118.     exit(EXIT_FAILURE);
  119.     }
  120.     /* Setup path */
  121.     if (vlSetupPaths(svr, (VLPathList)&path, 1, VL_SHARE, VL_SHARE) < 0) {
  122.     vlPerror("vlSetupPaths");
  123.     exit(EXIT_FAILURE);
  124.     }
  125.     UpdateTiming();
  126.     if (vlSelectEvents(svr, path,VLStreamPreemptedMask |
  127.                             VLControlChangedMask ) < 0) {
  128.             vlPerror("Select Events");
  129.             exit(EXIT_FAILURE);
  130.     }
  131.     /* Open the GL window for gfx transfers */
  132.     InitGfx(argc, argv);
  133.     /* Begin Transfers */
  134.     vlBeginTransfer(svr, path, 0, NULL);
  135.     /* The following sequence grabs each field and displays it in
  136.      * the GL window.
  137.      */
  138.     loop();
  139. }
  140.  
  141. void
  142. loop()
  143. {
  144.     XEvent event;
  145.     KeySym key;
  146.     XComposeStatus compose;
  147.     GLboolean clearNeeded = GL_FALSE;
  148.  
  149.     while (GL_TRUE) {
  150.         while(XPending(dpy)) {
  151.             XNextEvent(dpy, &event);
  152.             switch(event.type) {
  153.               case KeyPress:
  154.                 XLookupString(&event.xkey, NULL, 0, &key, NULL);
  155.                 switch (key) {
  156.                   case XK_Escape:
  157.                     exit(EXIT_SUCCESS);
  158.                   case XK_z:
  159.                     zoom = 3 - zoom; /* 2 -> 1, 1 -> 2 */
  160.             XMoveResizeWindow(dpy, window, 50, 0,
  161.                       zoom * size.xyVal.x, zoom * size.xyVal.y);
  162.                     glXWaitX();
  163.             glLoadIdentity();
  164.             glViewport(0, 0, zoom * size.xyVal.x - 1,
  165.                                zoom * size.xyVal.y - 1);
  166.             glOrtho(0, zoom * size.xyVal.x - 1,
  167.                             0, zoom * size.xyVal.y - 1, -1, 1);
  168.             clearNeeded = GL_TRUE;
  169.                     break;
  170.           case XK_i:
  171.                     if (hasInterlace) {
  172.                         interlace = !interlace;
  173.                         if (!interlace) {
  174.                             if (!glXMakeCurrentReadSGI(dpy, window,
  175.                                                        glxVideoSource, ctx)) {
  176.                                 fprintf(stderr,
  177.                                         "Can't make current to video\n");
  178.                                 exit(EXIT_FAILURE);
  179.                             }
  180.                         } else if (!glXMakeCurrent(dpy, window, ctx)) {
  181.                             fprintf(stderr,
  182.                                     "Can't make window current to context\n");
  183.                             exit(EXIT_FAILURE);
  184.                         }
  185.                         clearNeeded = GL_TRUE;
  186.                         printf("Interlace is %s\n", interlace ? "On" : "Off");
  187.                     } else {
  188.                         printf("Graphics interlacing is not supported\
  189.  by on this renderer\n");
  190.                     }
  191.             break;
  192.                   case XK_question:
  193.                   case XK_h:
  194.                     printf("Keys:\tz - toggle zoom (of 2)\n");
  195.                     printf("\ti - toggle interlacing/zooming of fields\n");
  196.                     printf("\th/? - print help\n");
  197.                     printf("\tEsc - exit\n");
  198.                 }
  199.                     break;
  200.             }
  201.         }
  202.     if (clearNeeded) {
  203.         glClear(GL_COLOR_BUFFER_BIT);
  204.         glXSwapBuffers(dpy, window);
  205.         glClear(GL_COLOR_BUFFER_BIT);
  206.         glXSwapBuffers(dpy, window);
  207.         clearNeeded = GL_FALSE;
  208.             glPixelZoom(zoom, -2 * zoom);
  209.             glRasterPos2f(0, zoom * size.xyVal.y - 1);
  210.     }
  211.         ProcessEvents();
  212.         GrabField(0);
  213.         glXSwapBuffers(dpy, window);
  214.         GrabField(1);
  215.         glXSwapBuffers(dpy, window);
  216.     }
  217. }
  218.  
  219. void
  220. usage(char *name, int exitStatus)
  221. {
  222.     fprintf(stderr, "usage: %s [-n#] [-v#] [-h (for help)]\n", name);
  223.     fprintf(stderr, "\t-n#   video device number (as reported by vlinfo)\n");
  224.     fprintf(stderr, "\t-v#   video input number (as reported by vlinfo)\n");
  225.     fprintf(stderr,
  226.             "\tInteractively, `h/?' keys provide description of interface\n");
  227.     exit(exitStatus);
  228. }
  229.  
  230. /*
  231.  * Open an X window of appropriate size and create context.
  232.  */
  233. void
  234. InitGfx(int argc, char **argv)
  235. {
  236.     int i;
  237.     XSizeHints hints;
  238.     int visualAttr[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 12,
  239.                         GLX_GREEN_SIZE, 12, GLX_BLUE_SIZE, 12,
  240.                         GLX_DEPTH_SIZE, 0, GLX_STENCIL_SIZE, 0,
  241.                         None};
  242.     const char *extensions;
  243.  
  244.     hints.x = 50; hints.y = 0;
  245.     hints.min_aspect.x = hints.max_aspect.x = size.xyVal.x;
  246.     hints.min_aspect.y = hints.max_aspect.y = size.xyVal.y;
  247.     hints.min_width = size.xyVal.x;
  248.     hints.max_width = 3 * size.xyVal.x;
  249.     hints.base_width = hints.width = size.xyVal.x;
  250.     hints.min_height = size.xyVal.y;
  251.     hints.max_height = 3 * size.xyVal.y;
  252.     hints.base_height = hints.height = size.xyVal.y;
  253.     hints.flags = USSize | PAspect | USPosition | PMinSize | PMaxSize;
  254.     createWindowAndContext(&dpy, &window, &ctx, 50, 0, size.xyVal.x,
  255.                            size.xyVal.y, GL_FALSE, &hints, visualAttr, argv[0]);
  256.     
  257.     extensions = glXQueryExtensionsString(dpy, DefaultScreen(dpy));
  258.     if (extensions == NULL ||
  259.         strstr(extensions, "GLX_SGI_make_current_read") == NULL) {
  260.         fprintf(stderr, "The make_current_read extension\
  261.  is not supported on this system\n");
  262.         exit(EXIT_FAILURE);
  263.     }
  264.     if (strstr(extensions, "GLX_SGIX_video_source") == NULL) {
  265.         fprintf(stderr, "The GLX video source extension\
  266.  is not supported on this system\n");
  267.         exit(EXIT_FAILURE);
  268.     }
  269.     glxVideoSource = glXCreateGLXVideoSourceSGIX(dpy, 0, svr, path,
  270.                                                  VL_GFX, drn);
  271.     if (glxVideoSource == NULL) {
  272.         fprintf(stderr, "Can't create glxVideoSource\n");
  273.         exit(EXIT_FAILURE);
  274.     }
  275.     if (!glXMakeCurrentReadSGI(dpy, window, glxVideoSource, ctx)) {
  276.     fprintf(stderr, "Can't make current to video\n");
  277.     exit(EXIT_FAILURE);
  278.     }
  279.     glLoadIdentity();
  280.     glViewport(0, 0, zoom * size.xyVal.x, zoom * size.xyVal.y);
  281.     glOrtho(0, zoom * size.xyVal.x, 0, zoom * size.xyVal.y, -1, 1);
  282.     glPixelZoom(zoom, -2 * zoom);
  283.     glRasterPos2f(0, zoom * size.xyVal.y - 1);
  284.     glReadBuffer(GL_FRONT);
  285.     /*
  286.      * Check for interlace extension.
  287.      */
  288.     hasInterlace =
  289.         strstr((const char *) extensions, "GL_SGIX_interlace") != NULL;
  290.     if (!hasInterlace) {
  291.         /*
  292.          * HACK - Interlace is not formally advertised.  Try getting it anyhow.
  293.          */
  294.         glDisable(GL_INTERLACE_SGIX);
  295.         hasInterlace = glGetError() == GL_NO_ERROR;
  296.         if (hasInterlace)
  297.             fprintf(stderr, "Assuming SGIX_Interlace supported but\
  298.  not advertised\n");
  299.     }
  300. }
  301.  
  302. /*
  303.  * Grab a field. A parameter of  1 = odd Field, 0 = Even Field.
  304.  * Use the global F1_is_first variable to determine how to interleave the fields.
  305.  */
  306. void
  307. GrabField(int odd_field)
  308. {
  309.     /* copy pixels from front to back buffer */
  310.     if (interlace) {
  311.     /* Restore zoom and transfer mode */
  312.     glRasterPos2i(0, 0);
  313.     glPixelZoom(1, 1);
  314.     glCopyPixels(0, 0, size.xyVal.x * zoom, size.xyVal.y * zoom, GL_COLOR);
  315.  
  316.     /* Copy the field from Sirius Video to GFX subsystem */
  317.         if (!glXMakeCurrentReadSGI(dpy, window, glxVideoSource, ctx)) {
  318.             fprintf(stderr, "Can't make current to video\n");
  319.         exit(EXIT_FAILURE);
  320.     }
  321.     if (odd_field) {
  322.         if (F1_is_first) {
  323.         /* F1 dominant, so odd field is first. */
  324.         glRasterPos2f(0, zoom * size.xyVal.y - 1);
  325.         } else {
  326.         /* F2 dominant, so even field is first. */
  327.         glRasterPos2f(0, zoom * (size.xyVal.y - 1) - 1);
  328.         }
  329.     } else {
  330.         if (F1_is_first) {
  331.         /* F1 dominant, so odd field is first. */
  332.         glRasterPos2f(0, zoom * (size.xyVal.y - 1) - 1);
  333.         } else {
  334.         /* F2 dominant, so even field is first. */
  335.         glRasterPos2f(0, zoom * size.xyVal.y - 1);
  336.         }
  337.     }
  338. #ifdef GL_SGIX_interlace
  339.     glEnable(GL_INTERLACE_SGIX);
  340. #endif
  341.         /* video is upside down relative to graphics */
  342.         glPixelZoom(zoom, -zoom);
  343.         glCopyPixels(0, 0, size.xyVal.x, size.xyVal.y/2, GL_COLOR);
  344.         if (!glXMakeCurrent(dpy, window, ctx)) {
  345.             fprintf(stderr, "Can't make current to original window\n");
  346.             exit(EXIT_FAILURE);
  347.         }
  348. #ifdef GL_SGIX_interlace
  349.     glDisable(GL_INTERLACE_SGIX);
  350. #endif
  351.     } else {
  352.     if (!odd_field) {
  353.         if (!F1_is_first) {
  354.         /* F1 dominant, so odd field is first. */
  355.         glRasterPos2f(0, zoom * size.xyVal.y - 1);
  356.         } else {
  357.         /* F2 dominant, so even field is first. */
  358.         glRasterPos2f(0, zoom * (size.xyVal.y - 1) - 1);
  359.         }
  360.     } else {
  361.         if (!F1_is_first) {
  362.         /* F1 dominant, so odd field is first. */
  363.         glRasterPos2f(0, zoom * (size.xyVal.y - 1) - 1);
  364.         } else {
  365.         /* F2 dominant, so even field is first. */
  366.         glRasterPos2f(0, zoom * size.xyVal.y - 1);
  367.         }
  368.     }
  369.         glCopyPixels(0, 0, size.xyVal.x, size.xyVal.y/2, GL_COLOR);
  370.     }
  371. }
  372.  
  373. void
  374. UpdateTiming(void)
  375. {
  376.     int is_525;
  377.  
  378.       /* Get the timing on selected input node */
  379.     if (vlGetControl(svr, path, src, VL_TIMING, &timing) <0) {
  380.     vlPerror("VlGetControl:TIMING");
  381.     exit(EXIT_FAILURE);
  382.     }
  383.     /* Set the GFX Drain to the same timing as input src */
  384.     if (vlSetControl(svr, path, drn, VL_TIMING, &timing) <0) {
  385.     vlPerror("VlSetControl:TIMING");
  386.     exit(EXIT_FAILURE);
  387.     }
  388.     if (vlGetControl(svr, path, drn, VL_SIZE, &size) <0) {
  389.     vlPerror("VlGetControl");
  390.     exit(EXIT_FAILURE);
  391.     }
  392.     /*
  393.      * Read the video source's field dominance control setting and timing,
  394.      * then set a variable to indicate which field has the first line, so that
  395.      * we know how to interleave fields to frames.
  396.      */
  397.     if (vlGetControl(svr, path, src,
  398.     VL_SIR_FIELD_DOMINANCE, &dominance) < 0) {
  399.     vlPerror("GetControl(VL_SIR_FIELD_DOMINANCE) on video source failed");
  400.     exit(EXIT_FAILURE);
  401.     }
  402.  
  403.     is_525 = ( (timing.intVal == VL_TIMING_525_SQ_PIX) ||
  404.            (timing.intVal == VL_TIMING_525_CCIR601) );
  405.  
  406.     switch (dominance.intVal) {
  407.     case SIR_F1_IS_DOMINANT:
  408.         if (is_525) {
  409.         F1_is_first = 0;
  410.         } else {
  411.         F1_is_first = 1;
  412.         }
  413.         break;
  414.     case SIR_F2_IS_DOMINANT:
  415.         if (is_525) {
  416.         F1_is_first = 1;
  417.         } else {
  418.         F1_is_first = 0;
  419.         }
  420.         break;
  421.     }
  422. }
  423.  
  424. void
  425. cleanup(void)
  426. {
  427.     vlEndTransfer(svr, path);
  428.     vlDestroyPath(svr, path);
  429.     vlCloseVideo(svr);
  430.     exit(EXIT_SUCCESS);
  431. }
  432.  
  433. void
  434. ProcessEvents(void)
  435. {
  436.     VLEvent ev;
  437.  
  438.     if (vlCheckEvent(svr, VLControlChangedMask|
  439.                      VLStreamPreemptedMask, &ev) == -1) {
  440.     return;
  441.     }
  442.     switch(ev.reason) {
  443.       case VLStreamPreempted:
  444.         cleanup();
  445.         exit(EXIT_SUCCESS);
  446.       case VLControlChanged:
  447.         switch(ev.vlcontrolchanged.type) {
  448.           case VL_TIMING:
  449.           case VL_SIZE:
  450.           case VL_SIR_FIELD_DOMINANCE:
  451.             UpdateTiming();
  452.             /* change the gl window size */
  453.             XResizeWindow(dpy, window, zoom * size.xyVal.x, zoom * size.xyVal.y);
  454.             glXWaitX();
  455.             printf("Resizing\n");
  456.         glLoadIdentity();
  457.             glViewport(0, 0, zoom * size.xyVal.x, zoom * size.xyVal.y );
  458.             glOrtho(0, zoom * size.xyVal.x, 0, zoom * size.xyVal.y, -1, 1);
  459.             break;
  460.           default:
  461.             break;
  462.         }
  463.             break;
  464.       default:
  465.     break;
  466.     }
  467. }
  468.